package com.eastfair.pay.chinaums.webPay;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.eastfair.pay.chinaums.common.utils.MerOrderIdUtil;
import com.eastfair.pay.chinaums.common.utils.TimeUtil;
import com.eastfair.pay.dto.ChinaumsDTO;
import com.eastfair.pay.entity.PayBody;
import com.eastfair.pay.enums.InstMidEnum;
import io.seata.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.validation.constraints.Size;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.time.LocalDateTime;

/**
 * @author kkqiao
 * 全民付移动支付公众号+服务窗支付下单接口
 * 说明：
 * 本接口为商户的订单H5页面向银商网络支付前置系统发起的支付跳转
 * 商户需遵循商户订单号生成规范，即以银商分配的4位来源编号作为账单号的前4位，且在商户系统中此
 * 账单号保证唯一。总长度需大于6位，小于28位。银商的推荐规则为（无特殊情况下，建议遵守此规则）：
 *      {来源编号(4位)}{时间(yyyyMMddmmHHssSSS)(17位)}{7位随机数}
 *  测试环境：http://58.247.0.18:29015/v1/netpay/webpay/pay
 *  生产环境：https://api-mop.chinaums.com/v1/netpay/webpay/pay
 */
@Slf4j
@Component
public class WebPay {

    @Value("${chinaums.appid}")
    private String appid;
    @Value("${chinaums.appkey}")
    private String appkey;
    @Value("${chinaums.payUrl}")
    private String url;
    @Value("${chinaums.mid}")
    private String mid;
    @Value("${chinaums.tid}")
    private String tid;

    public static void main(String[] args) throws Exception{
        //1. 组建请求报文
//        PayBody reqBody = new PayBody();
//        LocalDateTime now = LocalDateTime.now();
//        reqBody.setRequestTimestamp(LocalDateTimeUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
//        String timestamp = TimeUtil.getTimestamp(now);
//        reqBody.setMerOrderId(MerOrderIdUtil.getMerOrderId());
//        reqBody.setMid("898350579918007");
//        reqBody.setTid("B9BG9QTT");
//        reqBody.setInstMid("YUEDANDEFAULT");
//        reqBody.setTotalAmount("1");
//        reqBody.setSecureTransaction("false");
//        System.out.println("request body:\n"+reqBody);
//
//        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
//        String authorization = "OPEN-FORM-PARAM";
//        System.out.println("authorization:\n"+authorization);
//
//        String signature = getSignature(appid,appkey, timestamp,"nonce",reqBody.toString());
//
//        String URL = url + "?" + "authorization=" + authorization + "&appId=" + appid
//                + "&timestamp=" + timestamp + "&nonce=" + "nonce" + "&content=" + URLEncoder.encode(reqBody.toString(),"UTF-8")
//                + "&signature=" + URLEncoder.encode(signature,"UTF-8");
//        System.out.println("URL:" + URL);
        //3. 发送http请求，并解析返回信息
//        String response = request(URL);
//        System.out.println("response:\n"+response);
    }

    public ChinaumsDTO getInitiationOfPaymentsUrl(String totalAmount, String returnUrl,  String notifyUrl) throws Exception {
        //1. 组建请求报文
        PayBody reqBody = new PayBody();
        LocalDateTime now = LocalDateTime.now();
        reqBody.setRequestTimestamp(LocalDateTimeUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
        String timestamp = TimeUtil.getTimestamp(now);
        reqBody.setMerOrderId(MerOrderIdUtil.getMerOrderId());
        reqBody.setMid(mid);
        reqBody.setTid(tid);
        reqBody.setInstMid(InstMidEnum.YUEDANDEFAULT.getCode());
        reqBody.setTotalAmount(totalAmount);
        reqBody.setSecureTransaction("false");
        if(StringUtils.isNotEmpty(returnUrl)){
            reqBody.setReturnUrl(returnUrl);
        }
        if(StringUtils.isNotEmpty(notifyUrl)){
            reqBody.setNotifyUrl(notifyUrl);
        }
        log.info("request body:\n"+reqBody);

        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = "OPEN-FORM-PARAM";
        log.info("authorization:\n"+authorization);
        String signature = getSignature(appid,appkey, timestamp,"nonce",reqBody.toString());
        String URL = url + "?" + "authorization=" + authorization + "&appId=" + appid
                + "&timestamp=" + timestamp + "&nonce=" + "nonce" + "&content=" + URLEncoder.encode(reqBody.toString(),"UTF-8")
                + "&signature=" + URLEncoder.encode(signature,"UTF-8");
        log.info("URL:" + URL);
        ChinaumsDTO chinaumsDTO = new ChinaumsDTO();
        chinaumsDTO.setPayBody(reqBody);
        chinaumsDTO.setSignature(signature);
        chinaumsDTO.setUrl(URL);
        chinaumsDTO.setInstMid(reqBody.getInstMid());
        return chinaumsDTO;
    }

    /**
     * 发送httpGET请求
     * @param url 请求url
     * @return response
     */
    static String request(String url){
        StringBuffer sbf = new StringBuffer();
        String response = "";
        PrintWriter out = null;
        BufferedReader in = null;
        try{
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            HttpURLConnection httpUrlConnection = (HttpURLConnection) conn;
            httpUrlConnection.setRequestMethod("GET");
            httpUrlConnection.setReadTimeout(15000);
            httpUrlConnection.setReadTimeout(60000);
            httpUrlConnection.connect();
            in = new BufferedReader(new InputStreamReader(httpUrlConnection.getInputStream(),"UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                sbf.append(line);
                sbf.append("\r\n");
            }
            response = sbf.toString();
        }catch(Exception e){
            e.printStackTrace();
        } finally {
            try {
                if (out != null) { out.close();}
                if (in != null) {in.close();}
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return response;
    }

    /**
     * 获取签名头
     * @param appid
     * @param appkey
     * @param timestamp 格式:"yyyyMMddHHmmss"
     * @param nonce 随机字符串，
     * @param body 请求体
     * @return authorization 认证报文
     * @throws Exception
     */
    static String getSignature(String appid, String appkey, String timestamp, String nonce, String body) throws Exception {
        byte[] data = body.getBytes("utf-8");
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid+timestamp+nonce+testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appkey.getBytes("utf-8"),"HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes("utf-8"));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        return localSignatureStr;
    }

}
